//
// This file is part of cpp-lib, a library of C++ functions and classes.
// Cpp-lib is copyright (C) 2004 and onwards, The CPL Interest Group.
// 
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
// General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this library (see the file COPYING); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
// 02111-1307  USA
//
// $Id$
//
// Special Windoze stuff requiring linking with advapi32.dll, user32.dll
// and stuff like that.
//

#include <exception>
#include <stdexcept>
#include <string>
#include <sstream>

#include <cmath>

#include "cpp-lib/util.h"
#include "cpp-lib/sys/util.h"
#include "cpp-lib/windows/wrappers.h"
  

using namespace cpl::detail_ ;


namespace {


// Don't ask why it works, it just does. 

void exit_windows( bool reboot ) {

  HANDLE h ; 
  TOKEN_PRIVILEGES tkp ; 
   
  if( 
    !OpenProcessToken( 
      GetCurrentProcess() , 
      TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , 
      &h
     )
  ) { last_error_exception( "OpenProcessToken" ) ; }
   
  LookupPrivilegeValue( 0 , SE_SHUTDOWN_NAME , &tkp.Privileges[0].Luid ) ; 
   
  tkp.PrivilegeCount = 1 ;
  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ; 
   
  AdjustTokenPrivileges( h , FALSE , &tkp , 0 , 0 , 0 ) ; 
   
  if( ERROR_SUCCESS != GetLastError() )
  { last_error_exception( "AdjustTokenPrivileges" ) ; }

  UINT const f = ( reboot ? EWX_REBOOT : EWX_POWEROFF ) | EWX_FORCE ;
   
  if( !ExitWindowsEx( f , 0 ) ) 
  { last_error_exception( "ExitWindowsEx" ) ; }

}

} // anonymous namespace


void cpl::util::reboot  () { exit_windows( true  ) ; }
void cpl::util::poweroff() { exit_windows( false ) ; }
